/**
 * 数组转table
 * @param data 数组
 * @param td_style td的样式
 * @param tr_style tr的样式
 */
export default function start<T>(data: T[], td_style: string, tr_style: string) {
	const first_tr = 0;
	const col: any = [];
	const isArray = 0;
	const arr: any = [];
	const tr_first = 0;
	const tp_isArray = 0;
	const td = array2table(data, td_style, tr_style, first_tr, col, isArray, arr, tr_first, tp_isArray);
	return `<table>${td}</table>`;
}
function array2table<T>(data: T[], td_style: string, tr_style: string, first_tr: number, col: any, isArray: number, arr: any, tr_first: number, tp_isArray: number) {
	if (!data || !Array.isArray(data)) {
		return '<table></table>';
	} else {
		const tr_style_str = tr_style ? ` style="${tr_style}"` : '';
		const td_style_str = td_style ? ` style="${td_style}"` : '';
		// get all fields
		const fields = Array.from(data.reduce((m, row) => {
			Object.keys(row).forEach((field) => {
				m.add(field);
			});
			return m;
		}, new Set<string>()));
		let c = 0;
		const tb = data.reduce((trs, row: any) => {
			arr = [];
			tp(row, tr_first, arr, tp_isArray);
			const rowspan = Math.ceil(arr.reduce((sum: number, numa: number) => {
				return sum + numa;
			}));
			Object.values(row).forEach((item) => {
				if (Array.isArray(item)) {
					c = 1;
				}
			});
			if (c === 0) {
				c = 2;
				let i = 0;
				const tds = fields.reduce((colums, field) => {
					const value = row[field] || '';
					if (value !== '') {
						if (Array.isArray(value)) {
							first_tr = 0;
							const sub_table = array2table(value, td_style, tr_style, first_tr, col, isArray, arr, tr_first, tp_isArray);
							colums.push(`${sub_table}`);
						} else {
							col[i] = JSON.parse('{' + '"' + value + '":"' + value + '",' + '"colum":' + 1 + '}');
							if (i > 0) {
								if (col[i - 1][value] === value) {
									col[i - 1].colum++;
									colums[colums.length - 1] = `<td${td_style_str} colspan='${col[i - 1].colum}'>${value}</td>`;
								} else if (value !== '') {
									colums.push(`<td${td_style_str}>${value}</td>`);
								}
							} else if (value !== '') {
								colums.push(`<td${td_style_str}>${value}</td>`);
							}
							i++;
						}
					}
					return colums;
				}, [] as string[]).join('');
				trs.push(`${tds}</tr>`);
				col = [];
				isArray = 1;
			} else if (c === 1) {
				c++;
				let i = 0;
				const tds = fields.reduce((colums, field) => {
					first_tr++;
					const value = row[field] || '';
					if (value !== '') {
						if (Array.isArray(value)) {
							const sub_table = array2table(value, td_style, tr_style, first_tr, col, isArray, arr, tr_first, tp_isArray);
							colums.push(`${sub_table}`);
						} else {
							if (value !== '') {
								col[i] = JSON.parse('{' + '"' + value + '":"' + value + '",' + '"colum":' + 1 + '}');
							}
							if (first_tr === 1 || isArray === 1) {
								if (i > 0) {
									if (col[i - 1][value] === value) {
										col[i - 1].colum++;
										colums[colums.length - 1] = `<tr${tr_style_str}><td${td_style_str} rowspan='${rowspan}' colspan='${col[i - 1].colum}'>${value}</td>`;
									} else if (value !== '') {
										colums.push(`<tr${tr_style_str}><td${td_style_str} rowspan='${rowspan}'>${value}</td>`);
									}
								} else {
									colums.push(`<tr${tr_style_str}><td${td_style_str} rowspan='${rowspan}'>${value}</td>`);
								}
							} else {
								if (i > 0) {
									if (col[i - 1][value] === value) {
										col[i - 1].colum++;
										colums[colums.length - 1] = `<td${td_style_str} rowspan='${rowspan}' colspan='${col[i - 1].colum}'>${value}</td>`;
									} else if (value !== '') {
										colums.push(`<td${td_style_str} rowspan='${rowspan}' colspan='${col[i - 1].colum}'>${value}</td>`);
									}
								} else {
									colums.push(`<td${td_style_str} rowspan='${rowspan}'>${value}</td>`);
								}

							}
							isArray = 0;
							i++;
						}
					}
					return colums;
				}, [] as string[]).join('');
				trs.push(`${tds}`);
				col = [];
				first_tr = 0;
			} else {
				let i = 0;
				const tds = fields.reduce((colums, field) => {
					const value = row[field] || '';
					if (value !== '') {
						if (Array.isArray(value)) {
							const sub_table = array2table(value, td_style, tr_style, first_tr, col, isArray, arr, tr_first, tp_isArray);
							colums.push(`${sub_table}`);
						} else {
							col[i] = JSON.parse('{' + '"' + value + '":"' + value + '",' + '"colum":' + 1 + '}');
							if (i > 0) {
								if (col[i - 1][value] === value) {
									col[i - 1].colum++;
									colums[colums.length - 1] = `<td${td_style_str} colspan='${col[i - 1].colum}'>${value}</td>`;
								} else if (value !== '') {
									colums.push(`<td${td_style_str}>${value}</td>`);
								}
							} else if (value !== '') {
								colums.push(`<td${td_style_str}>${value}</td>`);
							}
							i++;
						}
					}
					return colums;
				}, [] as string[]).join('');
				trs.push(`<tr${tr_style_str}>${tds}</tr>`);
				col = [];
			}
			return trs;
		}, [] as string[]).join('');
		return `${tb}`;
	}
}

function tp(data: any, tr_first: number, arr: any, tp_isArray: number) {
	let data1 = data;
	if (!Array.isArray(data)) {
		data1 = [data];
	}
	const fields = Array.from(data1.reduce((m: any, row: any) => {
		Object.keys(row).forEach((field) => {
			m.add(field);
		});
		return m;
	}, new Set<string>()));
	let c = 0;
	data1.forEach((row: any) => {
		Object.values(row).forEach((item) => {
			if (Array.isArray(item)) {
				c = 1;
			}
		});
		if (c === 0) {
			c = 2;
			fields.forEach((field: any) => {
				const value = row[field] || '';
				if (Array.isArray(value)) {
					tr_first = 0;
					tp(value, tr_first, arr, tp_isArray);
				}
			});
			arr.push(0.5);
			tp_isArray = 1;
		} else if (c === 1) {
			c++;
			fields.forEach((field: any) => {
				tr_first++;
				const value = row[field] || '';
				if (Array.isArray(value)) {
					tp(value, tr_first, arr, tp_isArray);
				} else {
					if (tr_first === 1 || tp_isArray === 1) {
						arr.push(0.5);
					}
					tp_isArray = 0;
				}
			});
			tr_first = 0;
		} else {
			fields.forEach((colums, field: any) => {
				const value = row[field] || '';
				if (Array.isArray(value)) {
					tp(value, tr_first, arr, tp_isArray);
				}
				return colums;
			});
			arr.push(1);
		}
	});
}
